﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Linq;

namespace $safeprojectname$
{
    /// <summary>
    ///     filter object represents the base definiton of filters
    ///     to be used for handling the Entity's list.
    /// This common interface grants the same approach for filtering, ordering, paging... for all entities.
    /// </summary>
    /// <typeparam name = "TID"></typeparam>
    [Serializable]
    public abstract class Filter<TID> : IFilter<TID>
    {
        #region members
        int _takeRows;
        IList<TID> _itemPositionInList;
        IDictionary<string, string> _masterPageOptionsList;
        IDictionary<string, bool> _orderBy;
        IDictionary<string, string> _propertyList;
        string _targetMasterPageForLink = string.Empty;
        bool _hasDefaultValues = true;
        int _currentPage;
        int _skipRows;
        IList<string> _selectColumns;
        #endregion members

        #region constructor
        /// <summary>
        ///     Resets the default ListRowCount based on Web.config.
        ///     It could be reset ad hoc using the TakeRows property
        /// </summary>
        protected Filter()
        {
            _takeRows = Global.Settings.DefaultListRowCount;
        }
        #endregion constructor

        #region set ID filter
        public abstract void SetIdSearch(TID idSearch);
        #endregion set ID filter

        #region ICloneable
        public virtual object Clone()
        {
            var filter = MemberwiseClone() as Filter<TID>;

            filter.ItemPositionInList = new List<TID>(ItemPositionInList);
            filter.MasterPageOptionsList = new Dictionary<string, string>(MasterPageOptionsList);

            filter.OrderBy = new Dictionary<string, bool>(OrderBy);
            filter.ProjectionList = new Dictionary<string, string>(ProjectionList);

            return filter;
        }
        #endregion ICloneable

        #region properties
        /// <summary>
        ///     Total count of all rows matching filtering criteria.
        ///     Should be filled in Dao.Find()
        /// </summary>
        public virtual int TotalRows { get; set; }


        /// <summary>
        ///     SET Maximum rows count on a page.
        ///     In fact this value is always set, by default to 20.
        ///     In cases when the target is to find any - set it to 1.
        ///     When you want all records, set it to int.MaxValue
        /// </summary>
        public virtual int TakeRows
        {
            get { return _takeRows; }
            set
            {
                _takeRows = Math.Max(1, value);
                _skipRows = _currentPage * _takeRows;
            }
        }

        /// <summary>
        /// Could be used instead of the CurrentPage. CurrentPage will be calculated immediately
        /// </summary>
        public virtual int SkipRows
        {
            get { return _skipRows; }
            set
            {
                _skipRows = Math.Max(0, value);
                _currentPage = _skipRows / _takeRows;
            }
        }

        public virtual bool ShowInlineCount { get; set; }

        /// <summary>
        ///     Paging. This value is maintained by base controller
        ///     and keeps information about which is the currently navigated page
        /// </summary>
        public virtual int CurrentPage
        {
            get { return _currentPage; }
            set
            {
                _currentPage = Math.Max(0, value);
                _skipRows = _currentPage * _takeRows;
            }
        }

        /// <summary>
        ///     Keeps the current Item number (position in the list)
        ///     to allow paging base on single Item!
        /// </summary>
        public virtual int CurrentRow { get; set; }

        /// <summary>
        ///     The counted value! Allows to display on UI how many pages is in the storage
        /// </summary>
        public virtual int PageCount
        {
            get { return (TotalRows - 1) / TakeRows; }
        }

        /// <summary>
        ///     Tricky collection allowing sorting.
        ///     If the implementing collection is Dictionary[string, bool]
        ///     then even the position plays role.
        ///     The first added as firstly evaluated in the ORDER BY clause.
        /// </summary>
        public virtual IDictionary<string, bool> OrderBy
        {
            get { return _orderBy ?? (_orderBy = new Dictionary<string, bool>()); }
            set { _orderBy = value; }
        }

        public virtual string OrderRows { get; set; }

        /// <summary>
        /// Could be used to limit the resulting set of "columns"
        /// </summary>
        public virtual IList<string> SelectColumns
        {
            get { return _selectColumns ?? (_selectColumns = new List<string>()); }
            set { _selectColumns = value; }
        }

        /// <summary>
        ///     The list of properties to be selected for the List view (Find)
        ///     If empty, then Criteria.List&lt;T&gt;() is called.
        ///     If at least one pair exists, the ProjectionList Restriction is applied
        ///     And the SQL Select statement returnes only selected pairs.
        ///     The key is the property name ("Code", "Address.City").
        ///     If the value is not null, then it should mean the resulting entity property to be filled:
        ///     e.g. ["Address.City", "City"] means, that "Address.City" key is transfered to "City" property of current entity.
        ///     the City could be only virtual (not persisted) e.g. string City { get; protected set; }
        /// </summary>
        public virtual IDictionary<string, string> ProjectionList
        {
            get { return _propertyList ?? (_propertyList = new Dictionary<string, string>()); }
            set { _propertyList = value; }
        }

        /// <summary>
        ///     Smart switch informing if the filter criteria are filled (binded from the form)
        ///     Or empty (just created and not binded yet)
        /// </summary>
        public virtual bool HasDefaultValues
        {
            get
            {
                return _hasDefaultValues && CurrentPage == 0;
            }
            set { _hasDefaultValues = value; }
        }

        /// <summary>
        ///     Keeps the list of IDs of current page.
        ///     The ID of current item can be then found in this list -
        ///     That allows to quickly find out next or previous item
        /// </summary>
        public virtual IList<TID> ItemPositionInList
        {
            get { return _itemPositionInList ?? (_itemPositionInList = new List<TID>()); }
            set { _itemPositionInList = value; }
        }

        /// <summary>
        ///     If there is non empty value, then edit anchor on List view
        ///     will target this window (list will be displayed in one window
        ///     and detail+edit in another window)
        ///     This value is set to IListModel on every OnBeforeList() operation
        /// </summary>
        public virtual string TargetNameForLink { get; set; }

        /// <summary>
        ///     allowes to provide information about the
        ///     MasterPage, which should be used for this link.
        ///     (For example when the Target is different, and detail should be only with body and buttons)
        ///     Default should be string.Empty, meaning the default MasterPage to be used.
        /// </summary>
        public virtual string TargetMasterPageForLink
        {
            get { return _targetMasterPageForLink; }
            set { _targetMasterPageForLink = value; }
        }

        /// <summary>
        ///     This collection is used to render combobox on the filter screen
        ///     with the options of available MasterPages.
        ///     User can select, which one will be used for the detail view.
        ///     If this list is empty, WebControl should not be rendered at all
        ///     (until set e.g. on AopUrlHelper - contains lazily loaded empty collection)
        /// </summary>
        public virtual IDictionary<string, string> MasterPageOptionsList
        {
            get { return _masterPageOptionsList ?? (_masterPageOptionsList = new Dictionary<string, string>()); }
            set { _masterPageOptionsList = value; }
        }

        /// <summary>
        ///     Export to Excel setting.
        ///     This switch (when set to true) allows exporting of all selected records,
        ///     (hiding the MaxRows restriciton).
        ///     By default set to true in the 'OnBeforeListToExcel()'
        /// </summary>
        public virtual bool ExportAllRows { get; set; }

        /// <summary>
        /// if set to true, the list is returned from 0, when the required page is out of total pages
        /// </summary>
        public virtual bool AllowRewind { get; set; }
        #endregion properties
    }
}